#include <string>
#include <vector>
#include "StoreObjectDiff.h"
#include "Define.h"
#include "StoreObject.h"
#include "PublicFunction.h"

namespace gitstore {
template<>
ErrorStatus CStoreObjectDiff::diff<std::string, const std::string&>(const StoreObject& v1, const StoreObject& v2,
                              std::string& sres_diff, const std::string& seperator) {
    std::vector<std::string> vs1, vs2;

    splitString(v1.get(), vs1, seperator.c_str());
    splitString(v2.get(), vs2, seperator.c_str());


    //    std::string s1(v1.getData(), v1.getSize());
    //    std::string s2(v2.getData(), v2.getSize());
    MyersDiffRes res_diff;
    res_diff = emattsan::myers::diff(vs2, vs1);

    sres_diff.clear();

    sres_diff.reserve(1.3*(v1.get().size()>v2.get().size()?v1.get().size():v2.get().size()));
    auto ite1 = vs1.begin();
    auto ite2 = vs2.begin();
    for ( auto &diff : res_diff )
    {
        switch(diff)
        {
        case emattsan::myers::DELETE:
            sres_diff += (std::string("- ") + *ite2 + "\n");
            ++ite2;
            break;

        case emattsan::myers::COMMON:
            sres_diff += (std::string("  ") + *ite2 + "\n");
            ++ite2;
            ++ite1;
            break;

        case emattsan::myers::ADD:
            sres_diff += (std::string("+ ") + *ite1 + "\n");
            ++ite1;
            break;

//        default:
//            break;
        }
    }
    return Success;
}

template<>
ErrorStatus CStoreObjectDiff::diff<std::vector<std::string>>(const StoreObject& value1, const StoreObject& value2,
                                                  std::vector<std::string>& sres_diff) {
    set<string> diff_set;
    for ( auto iter = value1.mbegin() ; iter != value1.mend() ; iter++ ) {
        auto key = iter->first;
        if ( value2.isKeyExist(key) ) {
            diff_set.emplace(key);
            continue;
        } else {
            if ( iter->second.compare(value2.get(key)) != 0 ) {
                diff_set.emplace(key);
            }
        }
    }
    for ( auto iter = value2.mbegin() ; iter != value2.mend() ; iter++ ) {
        auto key = iter->first;
        if ( diff_set.find(key) != diff_set.end() )
            continue;
        if ( value1.isKeyExist(key) ) {
            diff_set.emplace(key);
            continue;
        } else {
            if ( iter->second.compare(value1.get(key)) != 0 ) {
                diff_set.emplace(key);
            }
        }
    }
    sres_diff.clear();
    sres_diff.reserve(diff_set.size());
    sres_diff.insert(sres_diff.begin(), diff_set.begin(), diff_set.end());
    return Success;
}

template<>
ErrorStatus CStoreObjectDiff::diff<std::vector<size_t>>(const StoreObject& value1, const StoreObject& value2,
                                             std::vector<size_t>& sres_diff) {
    if ( value1.size() > value2.size() ) {
        for ( size_t i = 0L; i<value2.size() ; i++ ) {
            if ( value1[i].compare(value2[i]) == 0 )
                continue;
            else {
                sres_diff.emplace_back(i);
            }
        }
        for ( size_t i = value2.size() ; i<value1.size() ; i++ ) {
            sres_diff.emplace_back(i);
        }
    } else {
        for ( size_t i = 0L; i<value1.size() ; i++ ) {
            if ( value1[i].compare(value2[i]) == 0 )
                continue;
            else {
                sres_diff.emplace_back(i);
            }
        }
        for ( size_t i = value1.size() ; i<value2.size() ; i++ ) {
            sres_diff.emplace_back(i);
        }
    }
    return Success;
}

//CDiff::CDiff()
//{

//}
//ErrorStatus CDiff::parseString(const StoreObject& v1, const StoreObject& v2,
//                        std::string& sres_diff, const std::string& seperator) {
//    std::vector<std::string> vs1, vs2;

//    splitString(v1.get(), vs1, seperator.c_str());
//    splitString(v2.get(), vs2, seperator.c_str());


//    //    std::string s1(v1.getData(), v1.getSize());
//    //    std::string s2(v2.getData(), v2.getSize());
//    MyersDiffRes res_diff;
//    res_diff = emattsan::myers::diff(vs2, vs1);

//    sres_diff.clear();

//    sres_diff.reserve(1.3*(v1.get().size()>v2.get().size()?v1.get().size():v2.get().size()));
//    auto ite1 = vs1.begin();
//    auto ite2 = vs2.begin();
//    for ( auto &diff : res_diff )
//    {
//        switch(diff)
//        {
//        case emattsan::myers::DELETE:
//            sres_diff += (std::string("- ") + *ite2 + "\n");
//            ++ite2;
//            break;

//        case emattsan::myers::COMMON:
//            sres_diff += (std::string("  ") + *ite2 + "\n");
//            ++ite2;
//            ++ite1;
//            break;

//        case emattsan::myers::ADD:
//            sres_diff += (std::string("+ ") + *ite1 + "\n");
//            ++ite1;
//            break;

//        default:
//            break;
//        }
//    }
//    return Success;
//}
}
